package dmwr.service;

import java.util.List;

import dmwr.bean.Entry;
import dmwr.bean.Pool;
import dmwr.bean.Shot;
import dmwr.bean.User;

public interface Service {

	Page<User> listUsers(int pageNum, int pageSize);

	User getUser(String username);

	void saveUser(User user) throws Duplicate;

	void deleteUser(String username);

	void createUserIfFirst(User user);

	Page<Pool> listPools(int pageNum, int pageSize);

	Pool getPool(Long id);

	void savePool(Pool pool) throws Duplicate;

	void deletePool(Long id);

	Page<Entry> listEntries(int pageNum, int pageSize);

	Entry getEntry(Long id);

	void saveEntry(Entry entry) throws Duplicate;

	void deleteEntry(Long id);

	// void addAllEntriesToPool(String poolTitle);

	Session getSession(String username, Long poolId, long length);

	void saveSession(String username, Long poolId, List<Answer> answers);

	void reset();

	public static class Page<T> {
		private final List<T> items;
		private final Integer prevPageNum;
		private final Integer nextPageNum;

		public Page(List<T> items, Integer prevPageNum, Integer nextPageNum) {
			this.items = items;
			this.prevPageNum = prevPageNum;
			this.nextPageNum = nextPageNum;
		}

		public List<T> getItems() {
			return items;
		}

		public Integer getPrevPageNum() {
			return prevPageNum;
		}

		public Integer getNextPageNum() {
			return nextPageNum;
		}
	}

	public static class Duplicate extends Exception {
		private static final long serialVersionUID = 1L;
		private final Object existing;

		public Duplicate(Object existing) {
			this.existing = existing;
		}

		public Object getExisting() {
			return existing;
		}
	}

	public static class Session {
		private final long position;
		private final List<Entry> entries;
		private final long entryCount;
		private final List<Shot> shots;
		private final long lastShotCreated;
		private final Entry lastShotEntry;

		public Session(long current, List<Entry> entries, long entryCount,
				List<Shot> tests, long lastShotCreated, Entry lastShotEntry) {
			this.position = current;
			this.entries = entries;
			this.shots = tests;
			this.entryCount = entryCount;
			this.lastShotCreated = lastShotCreated;
			this.lastShotEntry = lastShotEntry;
		}

		public long getPosition() {
			return position;
		}

		public List<Entry> getEntries() {
			return entries;
		}

		public List<Shot> getShots() {
			return shots;
		}

		public long getEntryCount() {
			return entryCount;
		}

		public long getLastShotCreated() {
			return lastShotCreated;
		}

		public Entry getLastShotEntry() {
			return lastShotEntry;
		}
	}

	public static class Answer {
		private final long position;
		private final long entryId;
		private final boolean ok;

		public Answer(long position, long entryId, boolean ok) {
			this.position = position;
			this.entryId = entryId;
			this.ok = ok;
		}

		public long getPosition() {
			return position;
		}

		public long getEntryId() {
			return entryId;
		}

		public boolean isOk() {
			return ok;
		}
	}
}
